﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Cabal.Kernel.Provider
{
    public class UserControl:IResControl,IDisposable
    {
        public UserControl(CabalSoul kernel)
        {
            init(kernel, Path_Default);
        }
        public UserControl(CabalSoul kernel,string path)
        {
            init(kernel, path);
        }



        public const string Path_Default = "User.XML";
        public const string Regid_UserCollection = "User.XML";
        public const string XPath_UserRoot = "CabalSoul/UserCollection";
        public const string XPath_OnlineUsers = "OnlineUsers";
        public const string XPath_OnlineUsersA = "/OnlineUsers";
        public const string XPath_OfflineUser = "OfflineUser";
        public const string XPath_OfflineUserA = "/OfflineUser";
        public const string XPath_User = "User";

        CabalSoul _kernel;
        EnvSupport _support;
        string _path;

        //根据OperatorTime排序
        List<User> onOldUser = new List<User>();
        List<User> onNewUser = new List<User>();
        List<User> nocheckUser = new List<User>();
        List<User> offlineUser = new List<User>();

        /// <summary>
        /// 不保存MJ登录的状态（默认为false，保存登录状态）
        /// </summary>
        public bool User_NoSaveLoginState = false;
        /// <summary>
        /// 把老MJ也视为新MJ（既请求新马甲用光时返回老MJ，默认false，不视为老MJ）
        /// </summary>
        public bool User_OldBelongNew = false;

        ///// <summary>
        ///// 当已验证的在线MJ为空的时候直接使用未验证MJ（默认true，使用未验证MJ）
        ///// </summary>
        //public bool User_UseNocheckUser = true;




        void init(CabalSoul kernel, string path)
        {
            _kernel = kernel;
            _support = kernel.Support;
            _path = path;
        }
        void load()
        {
            _support.Register(Regid_UserCollection, _path);

            nocheckUser.Clear();
            onOldUser.Clear();
            offlineUser.Clear();

            XmlNode root = _support.ReadNode(Regid_UserCollection, XPath_UserRoot);
            XmlNode online = root.SelectSingleNode(XPath_OnlineUsers);
            XmlNode offline = root.SelectSingleNode(XPath_OfflineUser);

            foreach (XmlNode i in online.ChildNodes)
            {
                User user = new User(i);
                nocheckUser.Add(user);
            }
            foreach (XmlNode i in offline.ChildNodes)
            {
                User user = new User(i);
                offlineUser.Add(user);
            }
        }
        void save2xml()
        {
            XmlNode root = _support.ReadNode(Regid_UserCollection, XPath_UserRoot);
            XmlNode online = root.SelectSingleNode(XPath_OnlineUsers);
            XmlNode offline = root.SelectSingleNode(XPath_OfflineUser);

            online.RemoveAll();
            offline.RemoveAll();

            foreach (User i in onNewUser)  //在线新马甲
            {
                XmlNode node = _support.CreatElement(Regid_UserCollection, XPath_User);
                i.ToXmlNode(node);
                online.AppendChild(node);
            }
            foreach (User i in onOldUser) //在线老马甲
            {
                XmlNode node = _support.CreatElement(Regid_UserCollection, XPath_User);
                i.ToXmlNode(node);
                online.AppendChild(node);
            }
            foreach (User i in nocheckUser) //在线未验证马甲
            {
                XmlNode node = _support.CreatElement(Regid_UserCollection, XPath_User);
                i.ToXmlNode(node);
                online.AppendChild(node);
            }
            foreach (User i in offlineUser) //离线马甲
            {
                XmlNode node = _support.CreatElement(Regid_UserCollection, XPath_User);
                i.ToXmlNode(node);
                offline.AppendChild(node);
            }
        }
        void checkType(string type)
        {
            string lowType = type.ToLower();
            if (lowType != "user" && lowType != "all")
                throw ResourceException.Request_UnknowType(this, type);
        }

        public User RequestUser()
        {
            try
            {
                return RequestUser(true); //能返回新MJ就返回新MJ
            }
            catch
            {
                return RequestUser(false); //不然就只能返回老MJ了
            }
        }
        public User RequestUser(bool newUser)
        {
            if (newUser) //请求新MJ
            {
                if (onNewUser.Count > 0)
                    return RequestFirstUser(onNewUser);
                else
                {
                    if (User_OldBelongNew) //允许使用老MJ
                    {
                        if (onOldUser.Count > 0)
                            return RequestFirstUser(onOldUser);
                        else
                            throw ResourceException.User_AllEmpty;
                    }
                    else
                    {
                        throw ResourceException.User_NewEmpty;
                    }
                }
            }
            else //请求老MJ
            {
                if (onOldUser.Count > 0)
                    return RequestFirstUser(onOldUser);
                else
                    throw ResourceException.User_OldEmpty;
            }
        }
        public User RequestFirstUser(List<User> list)
        {
            User rtn = list[0];
            rtn.ResetOptTime(this, list);
            return rtn;
        }

        public void AddUser(User user)
        {
            user.Parent = this;
            user.ResetOptTime(false);
            nocheckUser.Add(user);
        }
        public void AddUser(User user,bool online)
        {
            //调用下一个函数 所以不需要调整OPTTIME和Parent
            AddUser(user, user.NeedVerify,online);
        }
        public void AddUser(User user,bool newUser,bool online)
        {
            user.Parent = this;
            if (online)
            {
                user.ResetOptTime(false); //此函数调整OPT TIME
                if (newUser)
                    onNewUser.Add(user);
                else
                    onOldUser.Add(user);
            }
            else
            {
                offlineUser.Add(user);
            }
        }

        public User PeekUser(bool newUser)
        {
            List<User> lst = (newUser) ? onNewUser : onOldUser;

            if (lst.Count == 0)
                throw (newUser) ? ResourceException.User_NewEmpty : ResourceException.User_OldEmpty;

            return lst[0];
        }

        public bool RemoveUser(User user)
        {
            bool rtn = false;
            foreach (List<User> i in new List<User>[] { onNewUser,onOldUser,offlineUser,nocheckUser })
            {
                rtn |= i.Remove(user);
            }
            return rtn;
        }
        public bool RemoveUser(User user,bool newUser,bool online,bool nocheck)
        {
            if (online)
            {
                if (newUser)
                    return onNewUser.Remove(user);
                else
                    return onOldUser.Remove(user);
            }
            else
            {
                if (nocheck)
                    return nocheckUser.Remove(user);
                else
                    return offlineUser.Remove(user);
            }
        }

        public void ClearUser()
        {
            onNewUser.Clear();
            onOldUser.Clear();
            offlineUser.Clear();
            nocheckUser.Clear();
        }
        public void ClearUser(bool newUser, bool online, bool nocheck)
        {
            if (online)
            {
                if (newUser)
                    onNewUser.Clear();
                else
                    onOldUser.Clear();
            }
            else
            {
                if (nocheck)
                    nocheckUser.Clear();
                else
                    offlineUser.Clear();
            }
        }

        public void SortUser(User user, bool newUser)
        {
            if (newUser)
                SortUser(user, onNewUser);
            else
                SortUser(user, onOldUser);
        }
        public void SortUser(User user, List<User> list)
        {
            if (list.Remove(user))
            {
                SortAdd(user, list);
            }
        }
        public void SortAdd(User user, List<User> list)
        {
            int min = 0;
            int max = list.Count - 1;
            int i = 0;
            for (i = (list.Count - 1) / 2; max - min > 1; i = (max + min) / 2) //折半查找
            {
                if (user.OperatorTime < list[i].OperatorTime)
                    max = i;
                else if (user.OperatorTime > list[i].OperatorTime)
                    min = i;
                else
                    break;

                if (max - min <= 1)
                    i = max;
            }
            list.Insert(i, user);
        }


 
        #region IProvider 成员

        /// <summary>
        /// 请求资源
        /// </summary>
        /// <param name="type">资源类型(user)</param>
        /// <param name="arg">参数 (null)返回任意类型MJ一个 (string) new-新MJ old-老MJ</param>
        /// <returns></returns>
        public object Request(string type, object arg)
        {
            checkType(type);

            if (arg == null)
            {
                return RequestUser();
            }
            else
            {
                string argc = "";
                
                //验证ARG
                try { argc = (string)arg; }
                catch { throw ResourceException.Request_ArgUnknow; }
                if (argc == null || argc == "")
                    throw ResourceException.Request_ArgUnknow;

                //bool newUser, online;
                //foreach (string i in argc)
                //{
                //    switch (i.ToLower())
                //    {
                //        case "new":
                //            newUser = true;
                //            break;
                //        case "old":
                //            newUser = false;
                //            break;
                //        case "online":
                //            online = true;
                //            break;
                //        case "offline":
                //            newUser = false;
                //            break;
                //        default:
                //            throw ResourceException.Request_ArgUnknow;
                //    }
                //}
                return RequestUser((argc.ToLower() == "new"));
            }
        }

        public bool Reload(string type)
        {
            checkType(type);
            try { load(); return true; }
            catch { return false; }
        }

        #endregion       


        #region IResControl 成员

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">类型(user)</param>
        /// <param name="arg">参数 (null)往未验证列表里添加用户 (string 使用","连接)new-新MJ old-老MJ online-在线 offline-离线</param>
        /// <param name="data">用户数据(User)</param>
        public void AddResource(string type, object arg, object data)
        {
            checkType(type);

            User user = null;
            try{user = (User)data;}
            catch{ throw ResourceException.Request_UnknowData;}

            if (arg == null)
            {
                AddUser(user);
            }
            else
            {
                string[] argc = null;

                //验证ARG
                try { argc = ((string)arg).Split(','); }
                catch { throw ResourceException.Request_ArgUnknow; }
                if (argc == null || argc.Length <=1)
                    throw ResourceException.Request_ArgUnknow;

                bool newUser, online;
                newUser = true; online = false;
                foreach (string i in argc)
                {
                    switch (i.ToLower())
                    {
                        case "new":
                            newUser = true;
                            break;
                        case "old":
                            newUser = false;
                            break;
                        case "online":
                            online = true;
                            break;
                        case "offline":
                            newUser = false;
                            break;
                        case "":
                            break;
                        default:
                            throw ResourceException.Request_ArgUnknow;
                    }
                }

                AddUser(user,newUser,online);
            }
        }

        public void Remove(string type, object data)
        {
            checkType(type);
            RemoveUser((User)data);
        }

        public void Clear(string type)
        {
            checkType(type);
            ClearUser();
        }

        public void Save()
        {
            save2xml();
            _support.Save(Regid_UserCollection, _path);
        }

        #endregion


        #region IDisposable 成员

        public void Dispose()
        {
            _support.UnRegister(Regid_UserCollection);
        }

        #endregion

        public override string ToString()
        {
            return "Cabal.Kernel.Provider.UserControl";
        }
    }


}


/*
 * 
 * <CabalSoul>
 *   <UserCollection>
 *     <FileInfo>
 *       <Version>1</Version>
 *     </FileInfo>
 *     
 *     <OnlineUsers>
|*       <User>
|*         <Username>bbzyd</Username>
|*         <Password>baobaobao</Password>
|*         <BDUSS>Fb8D3bSx-x3ObAAAAAAA...SVxFob4Sg94==</BUDSS>
|*         <LoginTime>2008-8-10 15:00</LoginTime>
|*         <UserType>Old</UserType>
|*         <PostBanned>True</PostBanned>
|*         <LoginBanned>False</LoginBanned>
|*         <BDSpaceBanned>False</BDSpaceBanned>
|*         <BDSpaceUseabel>False</BDSpaceUseabel>
|*         <MsgBanned>False</MsgBanned>
|*         <Tag />
|*       </User>
 *     </OnlineUsers>
 *     <OfflineUser>
 *     <OfflineUser>
 *     
 *   </UserCollection>
 * </CabalSoul>
 * 
 * 
 */
